package cn.fuxi2022.accounts.activity.service.impl;

import cn.fuxi2022.accounts.activity.mapper.GroupActivityMapper;
import cn.fuxi2022.accounts.activity.service.GroupActivityCountService;
import cn.fuxi2022.core.exception.SmartGroupException;
import cn.fuxi2022.core.utils.ExecutortUtils;
import cn.fuxi2022.model.empty.count.BarChart;
import cn.fuxi2022.model.empty.count.BasicBar;
import cn.fuxi2022.model.empty.count.DoughnutChart;
import cn.fuxi2022.model.empty.count.TempChart;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;

@Slf4j
@Service
public class GroupActivityCountServiceImpl implements GroupActivityCountService {

    @Autowired
    private GroupActivityMapper groupActivityMapper;

    @Override
    @Cacheable(value = "SmartGroup:activity", key = "'groupActivityCount'")
    public Map groupActivityCount() {
        long l1 = System.currentTimeMillis();

        // 创建线程池
        ThreadPoolExecutor threadPool = ExecutortUtils.getThreadPool();
        threadPool.submit(() -> {
        });

        // 线程1
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> groupActivityMapper.countActivity(), ExecutortUtils.getThreadPool());

        // 线程2
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            // 累加活动时长（秒）
            int time = groupActivityMapper.sumActivityTime();
            // 将秒转化为分钟
            return new BigDecimal(time).divide(new BigDecimal(60), 0, RoundingMode.HALF_UP).setScale(0, RoundingMode.DOWN).intValue();
        }, ExecutortUtils.getThreadPool());

        // 线程3
        CompletableFuture<Integer> future3 = CompletableFuture.supplyAsync(() -> {
            // 平均活动时长（秒）
            int time = groupActivityMapper.avgActivityTime();
            // 将秒转化为分钟
            return new BigDecimal(time).divide(new BigDecimal(60), 0, RoundingMode.HALF_UP).setScale(0, RoundingMode.DOWN).intValue();
        }, ExecutortUtils.getThreadPool());

        // 线程4
        CompletableFuture<List<DoughnutChart>> future4 = CompletableFuture.supplyAsync(this::activityTypeToMap, ExecutortUtils.getThreadPool());

        // 线程5
        CompletableFuture<BasicBar> future5 = CompletableFuture.supplyAsync(() -> setBasicBar(groupActivityMapper.activityMostStudent()), ExecutortUtils.getThreadPool());

        // 线程6
        CompletableFuture<BarChart> future6 = CompletableFuture.supplyAsync(() -> setBarChart(groupActivityMapper.registerMostStudent()), ExecutortUtils.getThreadPool());

        // 线程7
        CompletableFuture<BasicBar> future7 = CompletableFuture.supplyAsync(() -> setBasicBar(groupActivityMapper.registerAndActivity()), ExecutortUtils.getThreadPool());

        CompletableFuture<List<DoughnutChart>> future8 = CompletableFuture.supplyAsync(() -> groupActivityMapper.registerAndTime(), ExecutortUtils.getThreadPool());

        CompletableFuture<Integer> future9 = CompletableFuture.supplyAsync(() -> groupActivityMapper.activityStudentCount(), ExecutortUtils.getThreadPool());

        try {
            CompletableFuture.allOf(future1, future2, future3, future4, future5, future6, future7, future8, future9).get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
            throw new SmartGroupException("多线程统计数据失败");
        }

        long l2 = System.currentTimeMillis();

        log.info("groupActivityCount统计耗时时间{}", l2 - l1);

        HashMap<String, Object> data = new HashMap<>(7);
        try {
            data.put("countActivity", future1.get());
            data.put("sumActivityTime", future2.get());
            data.put("avgActivityTime", future3.get());
            data.put("activityTypeToMap", future4.get());
            data.put("activityMostStudent", future5.get());
            data.put("registerMostStudent", future6.get());
            data.put("registerAndActivity", future7.get());
            data.put("registerAndTime", future8.get());
            data.put("activityStudentCount", future9.get());
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
            throw new SmartGroupException("多线程统计获取数据失败");
        }

        return data;
    }

    @CacheEvict(value = "SmartGroup:activity", key = "'groupActivityCount'")
    @Override
    public void groupActivityRefresh() {
        log.info("groupActivityCount缓存已经清空");
    }

    public List<DoughnutChart> activityTypeToMap() {
        List<DoughnutChart> doughnutCharts = groupActivityMapper.activityTypeToMap();

        doughnutCharts.forEach(doughnutChart -> {
            switch (doughnutChart.getName()) {
                case "0":
                    doughnutChart.setName("其他");
                    break;
                case "1":
                    doughnutChart.setName("授课");
                    break;
                case "2":
                    doughnutChart.setName("开会");
                    break;
                case "3":
                    doughnutChart.setName("团建");
                    break;
                default:
                    doughnutChart.setName("其他");
            }
        });

        return doughnutCharts;
    }

    public BarChart setBarChart(List<TempChart> tempCharts) {
        ArrayList<String> yAxis = new ArrayList<>();
        ArrayList<Integer> data = new ArrayList<>();

        tempCharts.forEach(tempChart -> {
            yAxis.add(tempChart.getName());
            data.add(tempChart.getValue());
        });

        BarChart barChart = new BarChart();
        barChart.setYAxis(yAxis);
        barChart.setData(data);
        return barChart;
    }

    public BasicBar setBasicBar(List<TempChart> tempCharts) {
        ArrayList<String> xAxis = new ArrayList<>();
        ArrayList<Integer> data = new ArrayList<>();

        tempCharts.forEach(tempChart -> {
            xAxis.add(tempChart.getName());
            data.add(tempChart.getValue());
        });

        BasicBar barChart = new BasicBar();
        barChart.setXAxis(xAxis);
        barChart.setData(data);
        return barChart;
    }
}
